package agent.behaviour;

import jade.core.behaviours.SimpleBehaviour;
import jade.lang.acl.ACLMessage;
import util.Constant;
import agent.communication.AgentsCommunicationMsg;
import agent.enums.TypeAgent;
import agent.model.AbstractAgent;

/**
 * SimpleBehaviour servant à lire les messages qu'un agent reçoit.
 * @author Jean-François Augé & Guillaume Poças
 */
public class ReadMailBehaviour extends SimpleBehaviour {

	private static final long serialVersionUID = 1L;

	private AbstractAgent agent;

	/** 
	 * Constructeur.
	 * @param a, l'agent au quel est attaché le Behaviour
	 */
	public ReadMailBehaviour(AbstractAgent a) {
		super(a);
		agent = a;
	}

	/** 
	 * Lis un message à chaque cycle, répond ou prévient l'agent en fonction du message reçu.
	 */
	@Override
	public void action() {
		// bloquant tant qu'il n'y a pas de réponse
		ACLMessage msg = agent.receive();

		ACLMessage reply = null;
		String cmd = "";
		String[] args = null;
		double impotsRecus = 0, argent = 0;

		if (msg != null) {
			// Process the message
			if(Constant.DEBUG_COM) System.out.println(agent.getLocalName()+" < "+msg.getContent());

			// call for proposal
			if(msg.getPerformative() == ACLMessage.CFP) {
				reply = msg.createReply();
				reply.setPerformative(ACLMessage.PROPOSE);
				cmd = AgentsCommunicationMsg.PROPOSE
						.makeCommand(String.valueOf(agent.getStockProductionCourant()), String.valueOf(agent.getPrixProduit()));
				if(Constant.DEBUG_COM) System.out.println(agent.getLocalName()+" > "+cmd);
				reply.setContent(cmd);
				agent.send(reply);
			} else if (msg.getPerformative() == ACLMessage.PROPOSE) {
				agent.setQuantite(agent.getReponsePropMissing()-1, Double.valueOf(msg.getContent().split("\\s")[1]));
				agent.setPrixProp(agent.getReponsePropMissing()-1, Double.valueOf(msg.getContent().split("\\s")[2]));
				agent.setMarchandContactes(agent.getReponsePropMissing()-1, msg.getSender());
				agent.setReponsePropMissing(agent.getReponsePropMissing()-1);

				if(agent.getReponsePropMissing() == 0) {
					// traite les réponses
					// calcul le prix le plus bas
					for(int i=0; i<agent.getMarchandsContactes().length; i++)
						if(agent.getPrixProp()[i] < agent.getPrixLePlusBas()) {
							agent.setPrixLePlusBas(agent.getPrixProp()[i]);
							agent.setMarchandChoisi(i);
						}
					// calcul la quantite à acheter
					// regarde en fonction de l'argent disponible et du stock
					agent.setQuantiteRequise(agent.getQuantite()[agent.getMarchandChoisi()]);
					while(((agent.getPrixLePlusBas() * agent.getQuantiteRequise()) > agent.getArgent()) ||
							((agent.getStockConsommationCourant() + agent.getQuantiteRequise()) > agent.getStockConsommeMax()))
						agent.setQuantiteRequise(agent.getQuantiteRequise()-1);

					if(Constant.DEBUG_AGENT == agent.getAgent())
						System.out.println(agent.getLocalName()+" Lowest price "+agent.getPrixLePlusBas()+", Quantity "+agent.getQuantiteRequise());
					//System.out.println(agent.getLocalName()+" argent "+agent.getArgent());

					// envoit les refus
					if((agent.getMarchandsContactes().length-1) > 0) {
						cmd = AgentsCommunicationMsg.REJECT_PROPOSAL.makeCommand();
						agent.sendMsg(agent.getMarchandsContactes(), ACLMessage.REJECT_PROPOSAL,
								cmd, agent.getMarchandsContactes()[agent.getMarchandChoisi()]);
					}

					// envoit la demande d'achat
					cmd = AgentsCommunicationMsg.ACCEPT_PROPOSAL.makeCommand(String.valueOf(agent.getQuantiteRequise()));
					agent.sendMsg(agent.getMarchandsContactes()[agent.getMarchandChoisi()], ACLMessage.ACCEPT_PROPOSAL, cmd);
				}
			}
			else if(msg.getPerformative() == ACLMessage.ACCEPT_PROPOSAL) {
				// changer le stock et l'argent
				double quantite = Double.valueOf(msg.getContent().split("\\s")[1]);
				if(agent.vendRessource(agent.getPrixProduit(), quantite) == false)
					System.out.println("Problème Vente ressources "+agent.getLocalName()+" : prix="+(quantite*agent.getPrixLePlusBas())+", quantite="+quantite+", stock="+agent.getStockProductionCourant());
				// on peut confirmer la transaction
				else {
					reply = msg.createReply();
					reply.setPerformative(ACLMessage.CONFIRM);
					cmd = AgentsCommunicationMsg.CONFIRM.makeCommand();
					if(Constant.DEBUG_COM) System.out.println(agent.getLocalName()+" > "+cmd);
					reply.setContent(cmd);
					agent.send(reply);
				}
			} else if(msg.getPerformative() == ACLMessage.REJECT_PROPOSAL) {
				// refus
			} else if(msg.getPerformative() == ACLMessage.CONFIRM) {
				// confirmation
				if(agent.acheteRessource((agent.getQuantiteRequise()*agent.getPrixLePlusBas()), agent.getQuantiteRequise()) == false)
					System.out.println("Problème Achat ressources "+agent.getLocalName()+" à "+agent.getMarchandChoisi()+" : prix="+(agent.getQuantiteRequise()*agent.getPrixLePlusBas())+", quantite="+agent.getQuantiteRequise()+", argentDispo="+agent.getArgent());
				if(Constant.DEBUG_TRADE)
					System.out.println(agent.getLocalName()+" "+agent.getArgent()+"€ "+agent.getStockConsommationCourant()+" "+agent.getRessourceConsommee());
			} else if(msg.getPerformative() == ACLMessage.INFORM) {
				//impots
				args = msg.getContent().split("\\s");
				if(args[(args.length-2)].equals("IMPOTS") && agent.getAgent().equals(TypeAgent.Roi)){
					impotsRecus = Double.parseDouble(args[(args.length-1)]);
					argent = agent.getArgent();
					//agent.vendRessource(impotsRecus, 0.0);
					agent.setArgent(argent+impotsRecus);
					System.out.println("Le Roi a recu un impot : "+impotsRecus);
				}
				else	System.out.println("Erreur réception cible impots !!");
			}
		} else
			block(); // schedules next execution
	}

	/** 
	 * Test la condition d'arrêt du comportement, ici la mort de l'agent.
	 * @return true si l'agent n'existe plus
	 */
	@Override
	public boolean done() {
		if(agent.isMort()) {
			System.out.println("read mail done");
			return true;
		}
		else return false;
	}

}
